; haribote-ipl
; TAB=4

CYLS	EQU		10				; 要读取到什么程度，意思是CYLS(cylinders) = 10，10个柱面

		ORG		0x7c00			; 指明程序的装载地址（origin）

; 以下的记述用于标准FAT12格式的软盘

		JMP		entry			; JMP - 跳转到指定的内存地址jump
		DB		0x90
		DB		"HELLOIPL"		; 启动区的名称可以是任意的字符串（8字节）
		DW		512				; 每个扇区（sector）的大小（必须为512字节）
		DB		1				; 簇（cluster）的大小（必须为1个扇区）
		DW		1				; FAT的起始位置（一般从第一个扇区开始）
		DB		2				; FAT的个数（必须为2）
		DW		224				; 根目录的大小（一般设成224项）
		DW		2880			; 该磁盘的大小（必须是2880扇区）
		DB		0xf0			; 磁盘的种类（必须是0xf0）
		DW		9				; FAT的长度
		DW		18				; 1个磁道（track）有几个扇区（必须是18）
		DW		2				; 磁头数（必须是2）
		DD		0				; 不使用分区，必须是0
		DD		2880			; 重写一次磁盘大小
		DB		0,0,0x29		; 意义不明，固定 
		DD		0xffffffff		; （可能是）卷标号码
		DB		"HARIBOTEOS "	; 磁盘的名称（11字节）
		DB		"FAT12   "		; 磁盘格式名称（8字节）
		RESB	18				; 先空出18字节

; 程序核心

entry:
		MOV		AX,0			; AX - 累加寄存器 初始化寄存器 赋值语句MOV: move（赋值而不是移动）
		MOV		SS,AX			; SS - 栈段寄存器
		MOV		SP,0x7c00		; SP - 栈指针寄存器
		MOV		DS,AX			; DS - 数据段寄存器
		
; 读磁盘

		MOV		AX,0x0820
		MOV		ES,AX
		MOV		CH,0			; 柱面0
		MOV		DH,0			; 磁头0
		MOV		CL,2			; 扇区2（含有IPL的启动区位于C0-H0-S1，所以我们从C0-H0-S2读取）
readloop:
		MOV		SI,0			; 记录失败次数的寄存器
; 尝试5次还不成功就跳转到error
retry:
		MOV		AH,0x02			; AH=0x02 : 读盘
		MOV		AL,1			; 1个扇区
		MOV		BX,0
		MOV		DL,0x00			; 0号，也就是A驱动器
		INT		0x13			; 调用磁盘BIOS
		JNC		next			; JNC - 条件跳转指令之一，进位标志是0的话就跳转Jump if not carry，没出错时跳转到next
		ADD		SI,1			; 往SI加1
		CMP		SI,5			; 比较SI与5
		JAE		error			; JAE - 条件跳转指令之一，大于或等于时跳转Jump if above or equal，SI >= 5时，跳转到error
		MOV		AH,0x00
		MOV		DL,0x00			; A驱动器
		INT 	0x13			; 重置驱动器
		JMP		retry

next:
		MOV		AX,ES			; 把内存地址后移0x200（ESx16+BX）
		ADD		AX,0x0020
		MOV		ES,AX			; 因为没有ADD ES,0x020指令，所以这里稍微绕个弯
		ADD		CL,1			; 往CL里加1
		CMP		CL,18			; 比较CL与18（我们要一直读到18扇区）
		JBE		readloop		; JBE - 条件跳转指令之一，小于等于则跳转Jump if below or equal，如果CL <= 18 跳转至readloop
		MOV		CL,1
		ADD		DH,1
		CMP		DH,2
		JB 		readloop		; JB - 条件跳转指令之一，小于就跳转Jump if below，如果DH < 2，则跳转到readloop
		MOV		DH,0
		ADD		CH,1
		CMP		CH,CYLS
		JB		readloop		; 如果CH < CYLS，则跳转到readloop

; 因为看完了实行haribote.sys !

		MOV		[0x0ff0],CH		; IPL读到什么程度的笔记（将CYLS的值写到内存地址0x0ff0中）
		JMP		0xc200

error:
		MOV		SI,msg

putloop:
		MOV		AL,[SI]			; AL - 累加寄存器低位
		ADD		SI,1			; ADD - 加法指令 给SI加1
		CMP		AL,0			; CMP - 比较指令compare
		JE		fin				; JE - 条件跳转指令中之一 相当于 if (AL == 0) { goto fin; }
		MOV		AH,0x0e			; AH - 累加寄存器高位 显示一个文字
		MOV		BX,15			; BX - 基址寄存器 指定字符颜色
		INT		0x10			; INT - 软件中断指令interrupt 调用显卡BIOS
		JMP		putloop

fin:
		HLT						; 让CPU停止，等待指令halt
		JMP		fin				; 无限循环

msg:
		DB		0x0a, 0x0a		; 换行2次
		DB		"load, error!"
		DB		0x0a			; 换行
		DB		0

		RESB	0x7dfe-$		; 填写0x00，直到0x001fe

		DB		0x55, 0xaa